<template>
  <div class="map-container" ref="mapContainer">
    <div v-if="!isMapLoaded" class="loading-indicator">
      <div class="spinner"></div>
      <div class="loading-text">加载中国地图数据...</div>
    </div>
    
    <!-- 选中省份信息面板 -->
    <div class="data-info" v-if="selectedProvince">
      <h3>{{ selectedProvince.name }}</h3>
      <div class="data-row">
        <span class="label">销售额:</span> 
        <span class="value">{{ formatCurrency(selectedProvince.salesAmount) }}</span>
      </div>
      <div class="data-row">
        <span class="label">订单数:</span> 
        <span class="value">{{ selectedProvince.orderCount }} 个</span>
      </div>
      <div class="data-row">
        <span class="label">产品数:</span> 
        <span class="value">{{ selectedProvince.productCount }} 件</span>
      </div>
    </div>
    
    <!-- 删除 legend 相关 HTML -->
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { getOrdersByProvince } from '../../api/auth';
import { createChinaMap } from './ChinaMapBuilder.js';

// 状态变量
const mapContainer = ref(null);
const isMapLoaded = ref(false);
const provinceData = ref([]);
const selectedProvince = ref(null);

// 加载省份销售数据
const loadProvinceData = async () => {
  try {
    const response = await getOrdersByProvince();
    if (response && response.data && response.data.code === 200) {
      provinceData.value = response.data.data || [];
    }
  } catch (error) {
    console.error('加载省份销售数据失败:', error);
  }
};

// 格式化货币
const formatCurrency = (value) => {
  if (!value && value !== 0) return '暂无数据';
  return new Intl.NumberFormat('zh-CN', {
    style: 'currency',
    currency: 'CNY',
    minimumFractionDigits: 2
  }).format(value) + '元';
};

// 根据销售额获取颜色
const getColorByAmount = (amount) => {
  if (!amount && amount !== 0) return new THREE.Color(0x3C7EBB); // 默认蓝色
  
  if (amount > 100000) {
    return new THREE.Color(0xFF3B30); // 高销售额：更鲜明的红色
  } else if (amount > 50000) {
    return new THREE.Color(0xFFCC00); // 中等销售额：更鲜明的黄色
  } else {
    return new THREE.Color(0x34C759); // 低销售额：更鲜明的绿色
  }
};

// 获取省份销售数据
const getProvinceSalesData = (provinceName) => {
  if (!provinceData.value || !provinceName) return null;
  
  // 处理省份名称差异
  const normalizedName = provinceName.replace(/(省|市|自治区|特别行政区)$/, '');
  
  // 寻找匹配的省份数据
  return provinceData.value.find(item => {
    const dataName = item.provinceName.replace(/(省|市|自治区|特别行政区)$/, '');
    return dataName === normalizedName || dataName.includes(normalizedName) || normalizedName.includes(dataName);
  });
};

/**
 * Three.js 初始化函数
 */
const initThree = async () => {
  // 获取容器元素，如果不存在则返回空清理函数
  const container = mapContainer.value;
  if (!container) return () => {};
  
  // 创建场景 
  // 场景是容纳所有3D对象的容器，就像是一个3D世界
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x001a3d); // 设置深蓝色背景

  // 设置相机 
  // 计算容器的宽高比，用于保持画面不变形
  const aspect = container.clientWidth / container.clientHeight;
  
  // 创建透视相机，模拟人眼视角
  // 参数说明：视场角30度，宽高比，近裁剪面0.1，远裁剪面1000
  const camera = new THREE.PerspectiveCamera(30, aspect, 0.1, 1000);
  
  // 设置相机位置为(0, 80, 80)，表示在场景右上方
  camera.position.set(10, 80, 50);
  
  // 设置相机朝向，看向场景中心点(0, 0, 0)
  camera.lookAt(10, 10,10);

  // 创建渲染器 
  // 使用WebGL技术进行渲染
  const renderer = new THREE.WebGLRenderer({ 
    antialias: true,        // 设置抗锯齿
  });
  
  // 设置渲染尺寸为容器大小
  renderer.setSize(container.clientWidth, container.clientHeight);
  
  // 设置像素比，适配高分辨率屏幕
  renderer.setPixelRatio(window.devicePixelRatio);
  
  // 启用阴影渲染
  renderer.shadowMap.enabled = true;
  
  // 清空容器并添加渲染器的DOM元素
  container.innerHTML = '';
  container.appendChild(renderer.domElement);
  
  // 添加控制器 
  // 创建轨道控制器，允许鼠标操作（旋转、缩放、平移）
  const controls = new OrbitControls(camera, renderer.domElement);
  
  // 启用阻尼效果，让操作更平滑
  controls.enableDamping = true;
  controls.dampingFactor = 0.05; // 阻尼系数
  
  // 设置缩放限制
  controls.minDistance = 30; // 最小距离，防止过度放大
  controls.maxDistance = 250; // 最大距离，防止过度缩小
  
  // 设置旋转角度限制
  controls.minPolarAngle = 0; // 最小极角，允许从任何角度观看
  controls.maxPolarAngle = Math.PI; // 最大极角，允许从任何角度观看
  
  // 启用旋转功能，禁用自动旋转
  controls.enableRotate = true;
  controls.autoRotate = false;
  
  // 设置灯光 
  // 添加环境光，提供基础照明，减少直射光对比度
  scene.add(new THREE.AmbientLight(0xffffff, 0.6));
  
  
  // 添加辅助光源，平衡光照，减少阴影过重
  const fillLight = new THREE.DirectionalLight(0xffffff, 0.3);
  fillLight.position.set(-50, 40, 50);
  scene.add(fillLight);
  
  // 加载数据和创建地图 
  // 先加载省份销售数据
  await loadProvinceData();
  
  // 创建中国地图3D模型
  const chinaMap = await createChinaMap(scene, getProvinceSalesData, getColorByAmount);
  
  // 添加交互功能 
  // 创建光线投射器，用于检测鼠标点击的3D对象
  const raycaster = new THREE.Raycaster();
  
  // 创建鼠标坐标向量，用于存储鼠标位置
  const mouse = new THREE.Vector2();
  
  // 鼠标悬停效果处理 
  // 变量跟踪当前高亮的省份网格对象
  let currentHighlightedMesh = null;
  
  // 获取页面中的提示框DOM元素
  const tooltip = document.getElementById('province-tooltip');

  // 处理鼠标移动事件，实现省份悬停高亮效果

  const handleMouseMove = (event) => {
    // 获取渲染器DOM元素的位置信息
    const rect = renderer.domElement.getBoundingClientRect();
    
    // 将2D鼠标坐标转换为3D标准化坐标
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
    
    // 从相机位置发射光线，检测鼠标悬停的对象
    raycaster.setFromCamera(mouse, camera);
    
    // 检测光线与场景中所有对象的交点
    const intersects = raycaster.intersectObjects(scene.children, true);
    
    // 设置默认鼠标样式为普通指针
    document.body.style.cursor = 'default';
    
    // 如果之前有高亮的省份，恢复其原始材质
    if (currentHighlightedMesh && currentHighlightedMesh.userData && currentHighlightedMesh.userData.originalMaterial) {
      currentHighlightedMesh.material = currentHighlightedMesh.userData.originalMaterial;
      currentHighlightedMesh = null;
      
      // 隐藏提示框
      if (tooltip) {
        tooltip.style.display = 'none';
      }
    }
    
    // 检查是否有省份被鼠标悬停
    if (intersects.length > 0) {
      for (let i = 0; i < intersects.length; i++) {
        const object = intersects[i].object;
        
        // 检查对象是否为省份网格且包含省份数据
        if (object instanceof THREE.Mesh && object.userData && object.userData.provinceName) {
          // 设置鼠标样式为手型指针，表示可点击
          document.body.style.cursor = 'pointer';
          
          // 高亮当前省份，使用高亮材质
          if (object.userData.highlightMaterial) {
            object.material = object.userData.highlightMaterial;
            currentHighlightedMesh = object;
          }
          
          // 更新提示框内容和位置
          if (tooltip) {
            const provinceName = object.userData.provinceName;
            const salesAmount = object.userData.salesAmount || 0;
            const orderCount = object.userData.orderCount || 0;
            const productCount = object.userData.productCount || 0;
            
            // 格式化销售额
            const formattedSalesAmount = formatCurrency(salesAmount);
            
            // 更新提示框HTML
            tooltip.innerHTML = `
              <h4 style="margin: 0 0 10px 0; color: #00ffff; font-size: 18px; border-bottom: 1px solid rgba(0, 255, 255, 0.5); padding-bottom: 6px;">${provinceName}</h4>
              <div style="display: flex; justify-content: space-between; margin: 6px 0; font-size: 14px;">
                <span style="color: rgba(255, 255, 255, 0.8);">销售额:</span>
                <span style="font-weight: bold;">${formattedSalesAmount}</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin: 6px 0; font-size: 14px;">
                <span style="color: rgba(255, 255, 255, 0.8);">订单数:</span>
                <span style="font-weight: bold;">${orderCount} 个</span>
              </div>
              <div style="display: flex; justify-content: space-between; margin: 6px 0; font-size: 14px;">
                <span style="color: rgba(255, 255, 255, 0.8);">产品数:</span>
                <span style="font-weight: bold;">${productCount} 件</span>
              </div>
            `;
            
            // 更新提示框位置
            tooltip.style.left = `${event.clientX + 15}px`;
            tooltip.style.top = `${event.clientY - 15}px`;
            tooltip.style.display = 'block';
          }
          
          break;
        }
      }
    }
  };
  
  // 为渲染器DOM元素添加鼠标移动事件监听器
  renderer.domElement.addEventListener('mousemove', handleMouseMove);
  
  // 窗口大小变化处理 
  const handleResize = () => {
    if (!container) return;
    
    // 获取容器的新尺寸
    const width = container.clientWidth;
    const height = container.clientHeight;
    
    // 调整渲染器尺寸
    renderer.setSize(width, height);
    
    // 更新相机宽高比
    camera.aspect = width / height;
    
    // 更新相机投影矩阵，确保画面不变形
    camera.updateProjectionMatrix();
  };
  
  // 添加窗口大小变化事件监听器
  window.addEventListener('resize', handleResize);
  
  // 立即执行一次尺寸调整，确保初始状态正确
  handleResize();

  // 动画循环 
  const animate = () => {
    // 请求下一帧动画，实现循环渲染
    requestAnimationFrame(animate);
    
    // 更新控制器状态（处理用户交互）
    controls.update();
    
    // 渲染场景到屏幕
    renderer.render(scene, camera);
  };
  
  // 启动动画循环
  animate();
  
  // 资源清理函数 
  return () => {
    // 清空容器DOM内容
    if (container) container.innerHTML = '';
    
    // 移除事件监听器，防止内存泄漏
    window.removeEventListener('resize', handleResize);
    renderer.domElement.removeEventListener('mousemove', handleMouseMove);
    
    // 清理提示框DOM元素
    const tooltip = document.getElementById('province-tooltip');
    if (tooltip && tooltip.parentNode) {
      tooltip.parentNode.removeChild(tooltip);
    }
    
    // 遍历场景中的所有对象，释放几何体和材质资源
    scene.traverse((object) => {
      if (object instanceof THREE.Mesh) {
        // 释放几何体资源
        if (object.geometry) object.geometry.dispose();
        
        // 释放材质资源
        if (object.material) {
          if (Array.isArray(object.material)) {
            // 如果是材质数组，遍历释放每个材质
            object.material.forEach(material => material.dispose());
          } else {
            // 如果是单个材质，先释放纹理再释放材质
            if (object.material.map) object.material.map.dispose();
            object.material.dispose();
          }
        }
      }
    });
    
    // 释放控制器和渲染器资源
    controls.dispose();
    renderer.dispose();
  };
};

// 暴露给父组件的变量
defineExpose({
  isMapLoaded,
  provinceData,
  refresh: async () => {
    await loadProvinceData();
    // 重新创建地图
    if (cleanup) cleanup();
    cleanup = await initThree();
  }
});

let cleanup = null;

onMounted(() => {
  setTimeout(async () => {
    cleanup = await initThree();
  }, 100);
});

onUnmounted(() => {
  if (cleanup) cleanup();
});
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 100%;
  position: relative;
  min-height: 600px;
}

.loading-indicator {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #fff;
  z-index: 3;
}

.spinner {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 3px solid rgba(0, 183, 255, 0.3);
  border-top-color: rgba(0, 183, 255, 1);
  animation: spin 1s infinite linear;
  margin-bottom: 10px;
}

.loading-text {
  font-size: 16px;
  color: #fff;
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

.data-info {
  position: absolute;
  top: 20px;
  left: 20px;
  background-color: rgba(1, 18, 71, 0.8);
  border: 1px solid rgba(0, 183, 255, 0.6);
  border-radius: 8px;
  padding: 15px;
  color: white;
  z-index: 10;
  min-width: 250px;
  box-shadow: 0 0 20px rgba(0, 102, 255, 0.3);
}

.data-info h3 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #00b7ff;
  font-size: 20px;
  border-bottom: 1px solid rgba(0, 183, 255, 0.4);
  padding-bottom: 8px;
}

.data-row {
  display: flex;
  justify-content: space-between;
  margin: 8px 0;
  font-size: 16px;
}

.data-row .label {
  color: rgba(255, 255, 255, 0.8);
}

.data-row .value {
  font-weight: bold;
  color: #fff;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style> 